package com.qd.panda.service.space.publish;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.DateUtil;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.space.ParkSpaceDTO;
import com.qd.common.panda.domain.entity.space.publish.ParkSpacePublishDTO;
import com.qd.common.panda.domain.entity.space.publish.ParkSpacePublishLogDTO;
import com.qd.panda.model.*;
import com.qd.panda.service.info.ParkInfoService;
import com.qd.panda.service.park.CarParkService;
import com.qd.panda.service.space.ParkSpaceService;
import com.qd.panda.service.space.StateUtilService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 〈一句话功能简述〉<br>
 *
 * @author sjk
 * @create 2024-04-26 9:35
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ParkSpacePublishHolderService {

    private final ParkSpaceService parkSpaceService;
    private final ParkSpacePublishService parkSpacePublishService;
    private final ParkSpacePublishListService parkSpacePublishListService;
    private final ParkSpacePublishLogService parkSpacePublishLogService;
    private final ParkInfoService parkInfoService;
    private final CarParkService carParkService;

    @Transactional(rollbackFor = Exception.class)
    public void timedTransmission() {
        LocalDate now = LocalDate.now().plusDays(1);
        LocalDateTime nowTime = LocalDateTime.now();
        List<ParkSpacePublish> list = parkSpacePublishService.getListByLoopPublish(ConstantDto.SF1);
        if (!list.isEmpty()) {
            for (ParkSpacePublish parkSpacePublish : list) {
                if (parkSpacePublish.getLeaseType().equals(PandaConstant.LEASE_TYPE_DAY)) {
                    if (parkSpacePublish.getEndDate().isBefore(now)) {
                        continue;
                    }
                }
                send(parkSpacePublish, nowTime, now);
            }
            list.clear();
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public void save(ParkSpacePublishDTO dto) {
        CarPark carPark = Optional.ofNullable(carParkService.getById(dto.getParkId())).orElseThrow(() -> new ApiException("停车场ID值错误"));
        if (StringUtils.hasLength(carPark.getParkSpaceType())) {
            if (!carPark.getParkSpaceType().equals(PandaConstant.PARK_SPACE_TYPE4)) {
                throw new ApiException("不支持发布");
            }
        } else {
            throw new ApiException("请设置车位类型");
        }
        dto.setParkSpaceType(carPark.getParkSpaceType());

        List<ParkInfo> list = parkInfoService.getListByParkId(dto.getParkId());
        if (list.isEmpty()) {
            throw new ApiException("没有车位可以发布");
        }

        dto.setPublishId(IdWorker.getIdStr());
        List<ParkSpacePublishList> parkSpacePublishLists = new ArrayList<>(list.size());
        for (ParkInfo parkInfo : list) {
            send(dto, parkInfo);
            buildPublishList(dto, parkInfo, parkSpacePublishLists);
        }
        parkSpacePublishService.save(dto);

        ParkSpacePublishLogDTO parkSpacePublishLogDTO = createPublishLog(dto);
        parkSpacePublishListService.saveBatch(parkSpacePublishLists);
        parkSpacePublishLogService.save(parkSpacePublishLogDTO);

        list.clear();
        parkSpacePublishLists.clear();
        parkSpacePublishLogDTO.freeData();
    }

    private void send(ParkSpacePublish parkSpacePublish, LocalDateTime nowTime, LocalDate now) {
        ParkSpacePublishDTO parkSpacePublishDTO = createPublishDTO(parkSpacePublish, nowTime, now);
        List<ParkSpacePublishList> parkSpacePublishLists = parkSpacePublishListService.getListByPublishId(parkSpacePublish.getPublishId());
        parkSpacePublishLists.forEach(parkSpacePublishList -> {
            send(parkSpacePublishDTO, parkSpacePublishList);
        });
        ParkSpacePublishLogDTO parkSpacePublishLogDTO = createPublishLog(parkSpacePublishDTO);
        parkSpacePublishLogService.save(parkSpacePublishLogDTO);

        parkSpacePublishDTO.freeData();
        parkSpacePublishLists.clear();
        parkSpacePublishLogDTO.freeData();
    }

    private void send(ParkSpacePublishDTO dto, ParkInfo parkInfo) {
        ParkSpaceDTO parkSpaceDTO = new ParkSpaceDTO();
        parkSpaceDTO.setPublisher(dto.getPublishId());
        parkSpaceDTO.setSid(IdWorker.getIdStr());
        parkSpaceDTO.setState(StateUtilService.STATE_1);
        parkSpaceDTO.setIsPublish(ConstantDto.SF1);
        parkSpaceDTO.setPublisher(dto.getOperator());
        parkSpaceDTO.setRentable(ConstantDto.SF1);
        parkSpaceDTO.setLeaseType(dto.getLeaseType());
        parkSpaceDTO.setStartDate(dto.getStartDate());
        parkSpaceDTO.setEndDate(dto.getEndDate());
        parkSpaceDTO.setStartHour(dto.getStartHour());
        parkSpaceDTO.setEndHour(dto.getEndHour());
        parkSpaceDTO.setAid(parkInfo.getAid());
        parkSpaceDTO.setPublishId(dto.getPublishId());
        parkSpaceDTO.setPublishTime(dto.getPublishTime());
        parkSpaceService.save(parkSpaceDTO);
        parkSpaceDTO.freeData();
    }

    private void send(ParkSpacePublishDTO dto, ParkSpacePublishList parkSpacePublishList) {
        ParkSpaceDTO parkSpaceDTO = new ParkSpaceDTO();
        parkSpaceDTO.setPublisher(parkSpacePublishList.getPublishId());
        parkSpaceDTO.setSid(IdWorker.getIdStr());
        parkSpaceDTO.setState(StateUtilService.STATE_1);
        parkSpaceDTO.setIsPublish(ConstantDto.SF1);
        parkSpaceDTO.setPublisher(dto.getOperator());
        parkSpaceDTO.setRentable(ConstantDto.SF1);
        parkSpaceDTO.setLeaseType(dto.getLeaseType());
        parkSpaceDTO.setStartDate(dto.getStartDate());
        parkSpaceDTO.setEndDate(dto.getEndDate());
        parkSpaceDTO.setStartHour(dto.getStartHour());
        parkSpaceDTO.setEndHour(dto.getEndHour());
        parkSpaceDTO.setAid(parkSpacePublishList.getAid());
        parkSpaceDTO.setPublishId(dto.getPublishId());
        parkSpaceDTO.setPublishTime(dto.getPublishTime());
        parkSpaceService.save(parkSpaceDTO);
        parkSpaceDTO.freeData();
    }

    private ParkSpacePublishLogDTO createPublishLog(ParkSpacePublishDTO dto) {
        ParkSpacePublishLogDTO logDTO = new ParkSpacePublishLogDTO();
        logDTO.setPublishLogId(IdWorker.getIdStr());
        logDTO.setPublishId(dto.getPublishId());
        logDTO.setPublishTime(dto.getPublishTime());
        logDTO.setDays(dto.getDays());
        logDTO.setStartDate(dto.getStartDate());
        logDTO.setEndDate(dto.getEndDate());
        logDTO.setStartHour(dto.getStartHour());
        logDTO.setEndHour(dto.getEndHour());
        return logDTO;
    }

    private void buildPublishList(ParkSpacePublishDTO dto, ParkInfo parkInfo, List<ParkSpacePublishList> mList) {
        ParkSpacePublishList parkSpacePublishList = new ParkSpacePublishList();
        parkSpacePublishList.setPublishId(dto.getPublishId());
        parkSpacePublishList.setSpaceNumber(parkInfo.getSpaceNumber());
        parkSpacePublishList.setSysSpaceNumber(parkInfo.getSysSpaceNumber());
        parkSpacePublishList.setAid(parkInfo.getAid());
        mList.add(parkSpacePublishList);
    }

    private ParkSpacePublishDTO createPublishDTO(ParkSpacePublish parkSpacePublish, LocalDateTime nowTime, LocalDate now) {
        ParkSpacePublishDTO parkSpacePublishDTO = new ParkSpacePublishDTO();
        parkSpacePublish.setPublishId(parkSpacePublish.getPublishId());
        parkSpacePublish.setPublishTime(nowTime);
        if (parkSpacePublish.getLeaseType().equals(PandaConstant.LEASE_TYPE_DAY)) {
            LocalDate startDate = parkSpacePublish.getStartDate().plusDays(parkSpacePublish.getDays());
            LocalDate endDate = parkSpacePublish.getEndDate().plusDays(parkSpacePublish.getDays());
            parkSpacePublishDTO.setStartDate(DateUtil.localDateToStr(startDate));
            parkSpacePublishDTO.setStartDate(DateUtil.localDateToStr(endDate));
        } else {
            parkSpacePublishDTO.setStartDate(DateUtil.localDateToStr(now));
            parkSpacePublishDTO.setEndDate(parkSpacePublishDTO.getStartDate());
            parkSpacePublishDTO.setStartHour(DateUtil.localTimeToString(parkSpacePublish.getStartHour()));
            parkSpacePublishDTO.setEndHour(DateUtil.localTimeToString(parkSpacePublish.getEndHour()));
        }
        parkSpacePublishDTO.setDays(parkSpacePublish.getDays());
        return parkSpacePublishDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    public void stop(ParkSpacePublishDTO dto) {
        ParkSpacePublishDTO parkSpacePublishDTO = Optional.ofNullable(parkSpacePublishService.getByIdDto(dto.getPublishId())).orElseThrow(() -> new ApiException("发布ID值错误"));
        if(parkSpacePublishDTO.getEnable().equals(ConstantDto.SF0)){
            throw new ApiException("已经停用，请勿重复操作");
        }
        parkSpacePublishDTO.setEnable(ConstantDto.SF0);
        parkSpacePublishService.update(parkSpacePublishDTO);
        List<ParkSpace> list = parkSpaceService.getListByPublishId(dto.getPublishId());
        if(!list.isEmpty()){
            for (ParkSpace parkSpace : list) {
                ParkSpaceDTO parkSpaceDTO = new ParkSpaceDTO();
                parkSpaceDTO.setSid(parkSpace.getSid());
                parkSpaceDTO.setState(StateUtilService.STATE_2);
                parkSpaceDTO.setEnd(ConstantDto.SF1);
                parkSpaceDTO.setRentable(ConstantDto.SF0);
                parkSpaceService.stop(parkSpaceDTO);
                parkSpaceDTO.freeData();
            }
            list.clear();
        }
        parkSpacePublishDTO.freeData();
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeBatchIds(List<String> ids) {
        for (String id : ids) {
            parkSpacePublishService.removeById(id);
            parkSpacePublishListService.removeByPublishId(id);
            parkSpacePublishLogService.removeByPublishId(id);
            List<ParkSpace> list = parkSpaceService.getListByPublishId(id);
            if(!list.isEmpty()){
                List<String> sidList = list.stream().map(ParkSpace::getSid).collect(Collectors.toList());
                parkSpaceService.removeBatchIds(sidList);
                sidList.clear();
            }
        }
        ids.clear();
    }
}